package com.pdd.commons.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.data.redis.connection.MessageListener;
import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
public class RedisUtils {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public void deleteFromRedis(String key) {
        redisTemplate.delete(key);
    }

    public Boolean hashCheckHxists(String mapName, String field) {
        return redisTemplate.opsForHash().hasKey(mapName, field);
    }

    public Object hashGet(String tableName, String hashKey) {
        return redisTemplate.opsForHash().get(tableName, hashKey);
    }

    public Map<Object, Object> hashGetAll(String key) {
        return  redisTemplate.opsForHash().entries(key);
    }

    public Long hashIncrementLongOfHashMap(String hKey, String hashKey, Long delta) {
        return redisTemplate.opsForHash().increment(hKey, hashKey, delta);
    }

    public Double hashIncrementDoubleOfHashMap(String hKey, String hashKey, Double delta) {
        return redisTemplate.opsForHash().increment(hKey, hashKey, delta);
    }

    public void hashPushHashMap(String key, Object hashKey, Object value) {
        redisTemplate.opsForHash().put(key, hashKey, value);
    }

    public Set<Object> hashGetAllHashKey(String key) {
        return redisTemplate.opsForHash().keys(key);
    }

    public Long hashGetHashMapSize(String key) {
        return redisTemplate.opsForHash().size(key);
    }

    public List<Object> hashGetHashAllValues(String key) {
        return redisTemplate.opsForHash().values(key);
    }

    public Long hashDeleteHashKey(String key, Object... hashKeys) {
        return redisTemplate.opsForHash().delete(key, hashKeys);
    }

    public void listLeftPushList(String key, String value) {
        redisTemplate.opsForList().leftPush(key, value);
    }

    public String listLeftPopList(String key) {
        return redisTemplate.opsForList().leftPop(key);
    }

    public Long listSize(String key) {
        return redisTemplate.opsForList().size(key);
    }

    public List<String> listRangeList(String key, Long start, Long end) {
        return redisTemplate.opsForList().range(key, start, end);
    }

    public Long listRemoveFromList(String key, long i, Object value) {
        return redisTemplate.opsForList().remove(key, i, value);
    }

    public String listIndexFromList(String key, long index) {
        return redisTemplate.opsForList().index(key, index);
    }

    public void listSetValueToList(String key, long index, String value) {
        redisTemplate.opsForList().set(key, index, value);
    }

    public void listTrimByRange(String key, Long start, Long end) {
        redisTemplate.opsForList().trim(key, start, end);
    }

    public void listRightPushList(String key, String value) {
        redisTemplate.opsForList().rightPush(key, value);
    }

    public String listRightPopList(String key) {
        return redisTemplate.opsForList().rightPop(key);
    }

    public String listRightPopList(String key,Long timeOut) {
        return redisTemplate.opsForList().rightPop(key,timeOut,TimeUnit.SECONDS);
    }

    public Long setAddSetMap(String key, String... values) {
        return redisTemplate.opsForSet().add(key, values);
    }

    public Long setGetSizeForSetMap(String key) {
        return redisTemplate.opsForSet().size(key);
    }

    public Set<String> setGetMemberOfSetMap(String key) {
        return redisTemplate.opsForSet().members(key);
    }

    public Boolean setCheckIsMemberOfSet(String key, Object o) {
        return redisTemplate.opsForSet().isMember(key, o);
    }

    public Integer stringAppendString(String key, String value) {
        return redisTemplate.opsForValue().append(key, value);
    }

    public String stringGetStringByKey(String key) {
        return  redisTemplate.opsForValue().get(key);
    }

    public String stringGetSubStringFromString(String key, long start, long end) {
        return redisTemplate.opsForValue().get(key, start, end);
    }

    public Long stringIncrementLongString(String key, Long delta) {
        return redisTemplate.opsForValue().increment(key, delta);
    }

    public Double stringIncrementDoubleString(String key, Double delta) {
        return redisTemplate.opsForValue().increment(key, delta);
    }

    public void stringSetString(String key, String value) {
        redisTemplate.opsForValue().set(key, value);
    }

    public void stringSetString(String key, String value,TimeUnit timeUnit,Long time) {
        redisTemplate.opsForValue().set(key, value);
    }

    public String stringGetAndSet(String key, String value) {
        return redisTemplate.opsForValue().getAndSet(key, value);
    }

    public void stringSetValueAndExpireTime(String key, String value, long timeout) {
        redisTemplate.opsForValue().set(key, value, timeout, TimeUnit.SECONDS);
    }

    public void setExpire(String key,long timeOut,TimeUnit time){
        redisTemplate.expire(key,timeOut,time);
    }

    public Long getExpire(String key){
        return redisTemplate.getExpire(key);
    }

    /**
     * redis订阅
     * @param key
     */
    public void subscribe(String key, MessageListener messageListener){
        redisTemplate.execute(new RedisCallback() {
            @Override
            public Object doInRedis(RedisConnection redisConnection) throws DataAccessException {
                redisConnection.subscribe(messageListener ,key.getBytes());
                return 1L;
            }
        });
    }
    /**
     * redis订阅
     * @param key
     */
    public Long publish(String key, String message){
        return redisTemplate.execute(new RedisCallback<Long>() {
            @Override
            public Long doInRedis(RedisConnection redisConnection) throws DataAccessException {
                Long result=redisConnection.publish(key.getBytes(),message.getBytes());
                return result;
            }
        });
    }

}